#ifndef	__ASSEMBLER__
#define	__ASSEMBLER__
#endif

#include <layout.h>
#include <mmu.h>

#define	RELOC(x)        ((x) - KBASE)

      // for multiboot header

#define	MULTIBOOT_PAGE_ALIGN   (1<<0)
#define	MULTIBOOT_MEMORY_INFO  (1<<1)
#define	MULTIBOOT_HEADER_MAGIC (0x1BADB002)
#define	MULTIBOOT_HEADER_FLAGS (MULTIBOOT_MEMORY_INFO | MULTIBOOT_PAGE_ALIGN)
#define	CHECKSUM               (-(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS))

	    .text
_kstart:
	    .code32
	    
	    // The Multiboot header
	    
	    .align 4
	    .long MULTIBOOT_HEADER_MAGIC
	    .long MULTIBOOT_HEADER_FLAGS
	    .long CHECKSUM
	    
	    .long _kstart
		
	    .long _text
	    .long _bss
	    .long _end
	    .long _start
		
	    .globl _start
_start:
	    movl  $RELOC(init_gdt_desc), %eax
	    lgdt  (%eax)
		
	    // Reload all segment register
	    movl  $GD_KERN_DATA, %eax
	    movw  %ax, %ds
	    movw  %ax, %es
	    movw  %ax, %ss
	    ljmp  $GD_KERN_TEXT, $relocated

relocated:
	    // initial stage stack
	    
	    movl  $0x0, %ebp
	    movl  $(init_stack_top), %esp
		
		// Call the c init procedure for further initailization
	    call  kern_main
	      	
	    .align PAGE_SIZE
		// force page alignment
	      
	    .globl init_vpd
init_vpd:	      
	    .space PAGE_SIZE

		.globl init_vpd_lock
init_vpd_lock:	      
	    .space PAGE_SIZE


		.align KSTACK_SIZE
	    // init stack space for kernel
	    .globl init_stack
init_stack:
	    .space KSTACK_SIZE
	    .globl init_stack_top
init_stack_top:
		
	    .align 4
	    // force 4 byte alignment
	      
init_gdt:
	    SEG_NULL
	    SEG(STA_X | STA_R, -KBASE, 0xffffffff)
	    SEG(STA_W, -KBASE, 0xffffffff)
init_gdt_desc:
	    // sizeof(init_gdt) - 1
	    .word 0x17
	    // address
	    .long RELOC(init_gdt)
